<template>
	<view class="html5-camera">
		<!-- 摄像头区域 -->
		<view v-if="showCamera && !capturedImage" class="camera-area">
			<!-- 使用原生HTML插入 -->
			<view class="video-wrapper" v-html="videoHtml"></view>
			
			<!-- 摄像头启动提示 -->
			<view v-if="!cameraReady" class="camera-loading">
				<view class="loading-content">
					<text class="loading-icon">📷</text>
					<text class="loading-text">{{ guideText }}</text>
				</view>
			</view>
		</view>
		
		<!-- 拍照结果预览 -->
		<view v-if="capturedImage" class="photo-preview">
			<image :src="capturedImage" class="preview-image" mode="aspectFit"></image>
		</view>
		
		<!-- 操作按钮 -->
		<view class="camera-controls">
			<view v-if="showCamera && !capturedImage" class="capture-controls">
				<button 
					class="capture-btn" 
					:class="{ disabled: !cameraReady || isCapturing }"
					@click="capturePhoto"
					:disabled="!cameraReady || isCapturing"
				>
					{{ isCapturing ? '拍照中...' : '拍照' }}
				</button>
			</view>
			
			<view v-if="capturedImage" class="result-controls">
				<button class="retry-btn" @click="retakePhoto">重新拍照</button>
				<button class="confirm-btn" @click="confirmPhoto">确认使用</button>
			</view>
		</view>
		
		<!-- Canvas容器 - 动态创建Canvas -->
		<view id="canvasContainer" style="display: none;"></view>
	</view>
</template>

<script setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue'

// Props
const props = defineProps({
	width: {
		type: Number,
		default: 400
	},
	height: {
		type: Number,
		default: 300
	}
})

// Emits
const emit = defineEmits(['success', 'cancel', 'error'])

// 响应式数据
const showCamera = ref(false)
const cameraReady = ref(false)
const capturedImage = ref('')
const isCapturing = ref(false)
const guideText = ref('正在启动摄像头...')
const videoHtml = ref('')

// 引用 - 不再需要 canvasRef，使用原生DOM获取

// 媒体流
let mediaStream = null
let videoElement = null

// 生命周期
onMounted(() => {
	initCamera()
})

onUnmounted(() => {
	cleanup()
})

// 方法
const initCamera = async () => {
	try {
		guideText.value = '正在请求摄像头权限...'
		
		// 请求摄像头权限
		mediaStream = await navigator.mediaDevices.getUserMedia({
			video: {
				facingMode: 'user',
				width: { ideal: props.width },
				height: { ideal: props.height }
			}
		})
		
		console.log('摄像头权限获取成功')
		
		// 创建视频HTML
		const videoId = 'html5Camera_' + Date.now()
		videoHtml.value = `
			<video 
				id="${videoId}" 
				autoplay 
				muted 
				playsinline 
				webkit-playsinline
				style="width: 100%; height: 100%; object-fit: cover; background: #000000; border-radius: 12px;"
			></video>
		`
		
		showCamera.value = true
		
		// 等待DOM更新
		await nextTick()
		
		// 延迟获取视频元素
		setTimeout(async () => {
			videoElement = document.getElementById(videoId)
			
			if (videoElement) {
				console.log('视频元素获取成功:', videoElement.constructor.name)
				
				// 设置媒体流
				videoElement.srcObject = mediaStream
				
				// 事件监听
				videoElement.addEventListener('loadedmetadata', () => {
					console.log('视频元数据加载完成')
					cameraReady.value = true
					guideText.value = '摄像头已就绪'
				})
				
				videoElement.addEventListener('playing', () => {
					console.log('视频开始播放')
					cameraReady.value = true
					guideText.value = '摄像头已就绪'
				})
				
				videoElement.addEventListener('error', (error) => {
					console.error('视频播放错误:', error)
					guideText.value = '视频播放失败'
				})
				
				// 播放视频
				try {
					await videoElement.play()
					console.log('视频播放成功')
				} catch (playError) {
					console.warn('自动播放失败:', playError)
					guideText.value = '请点击屏幕启动摄像头'
				}
			} else {
				throw new Error('无法获取视频元素')
			}
		}, 300)
		
	} catch (error) {
		console.error('摄像头初始化失败:', error)
		
		let errorMessage = '摄像头初始化失败'
		if (error.name === 'NotAllowedError') {
			errorMessage = '摄像头权限被拒绝'
		} else if (error.name === 'NotFoundError') {
			errorMessage = '未找到摄像头设备'
		} else if (error.name === 'NotReadableError') {
			errorMessage = '摄像头被其他程序占用'
		}
		
		guideText.value = errorMessage
		emit('error', errorMessage)
	}
}

const capturePhoto = async () => {
	if (!cameraReady.value || isCapturing.value || !videoElement) {
		console.log('拍照条件不满足:', {
			cameraReady: cameraReady.value,
			isCapturing: isCapturing.value,
			videoElement: !!videoElement
		})
		return
	}

	isCapturing.value = true

	try {
		console.log('开始拍照，视频元素信息:', {
			videoWidth: videoElement.videoWidth,
			videoHeight: videoElement.videoHeight,
			readyState: videoElement.readyState
		})

		// 动态创建Canvas元素
		const canvas = document.createElement('canvas')

		if (!canvas || typeof canvas.getContext !== 'function') {
			throw new Error('无法创建Canvas元素或getContext方法不存在')
		}

		console.log('Canvas元素创建成功:', canvas.constructor.name)

		const ctx = canvas.getContext('2d')

		if (!ctx) {
			throw new Error('无法获取Canvas 2D上下文')
		}

		// 设置Canvas尺寸
		const width = videoElement.videoWidth || props.width
		const height = videoElement.videoHeight || props.height

		canvas.width = width
		canvas.height = height

		console.log('Canvas尺寸设置:', { width, height })

		// 绘制视频帧
		ctx.drawImage(videoElement, 0, 0, width, height)

		// 转换为图片
		const imageDataUrl = canvas.toDataURL('image/jpeg', 0.8)

		if (!imageDataUrl || imageDataUrl === 'data:,') {
			throw new Error('图片数据生成失败')
		}

		capturedImage.value = imageDataUrl

		// 隐藏摄像头
		showCamera.value = false

		console.log('拍照成功，图片大小:', imageDataUrl.length, 'bytes')

		uni.showToast({
			title: '拍照成功',
			icon: 'success'
		})

		// 清理Canvas元素
		canvas.width = 0
		canvas.height = 0

	} catch (error) {
		console.error('拍照失败:', error)
		console.error('错误堆栈:', error.stack)

		uni.showToast({
			title: '拍照失败: ' + error.message,
			icon: 'none',
			duration: 3000
		})
	} finally {
		isCapturing.value = false
	}
}

const retakePhoto = () => {
	capturedImage.value = ''
	showCamera.value = true
	cameraReady.value = true
}

const confirmPhoto = () => {
	if (capturedImage.value) {
		emit('success', capturedImage.value)
		cleanup()
	}
}

const cleanup = () => {
	if (mediaStream) {
		mediaStream.getTracks().forEach(track => track.stop())
		mediaStream = null
	}
	
	if (videoElement) {
		videoElement.srcObject = null
		videoElement = null
	}
	
	showCamera.value = false
	cameraReady.value = false
	capturedImage.value = ''
	videoHtml.value = ''
}

// 暴露方法
defineExpose({
	initCamera,
	capturePhoto,
	cleanup
})
</script>

<style lang="scss" scoped>
.html5-camera {
	width: 100%;
	height: 100%;
	display: flex;
	flex-direction: column;
}

.camera-area {
	position: relative;
	flex: 1;
	min-height: 300px;
	background: #000000;
	border-radius: 12px;
	overflow: hidden;
}

.video-wrapper {
	width: 100%;
	height: 100%;
}

.camera-loading {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	bottom: 0;
	background: rgba(0, 0, 0, 0.7);
	display: flex;
	align-items: center;
	justify-content: center;
}

.loading-content {
	text-align: center;
	color: #ffffff;
}

.loading-icon {
	display: block;
	font-size: 48px;
	margin-bottom: 16px;
}

.loading-text {
	font-size: 16px;
}

.photo-preview {
	flex: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	background: #f5f5f5;
	border-radius: 12px;
	overflow: hidden;
}

.preview-image {
	max-width: 100%;
	max-height: 100%;
	border-radius: 8px;
}

.camera-controls {
	margin-top: 20px;
}

.capture-controls,
.result-controls {
	display: flex;
	gap: 16px;
	justify-content: center;
}

.capture-btn,
.retry-btn,
.confirm-btn {
	height: 48px;
	padding: 0 24px;
	border-radius: 24px;
	font-size: 16px;
	font-weight: 500;
	border: none;
	color: #ffffff;
	
	&.capture-btn {
		background: #007AFF;
		
		&.disabled {
			background: #cccccc;
		}
	}
	
	&.retry-btn {
		background: #ff9500;
	}
	
	&.confirm-btn {
		background: #34c759;
	}
}
</style>
